package com.csproj.basic.service;

import com.csproj.basic.BasicService;
import com.csproj.basic.domain.PDA;
import com.csproj.basic.domain.Site;
import com.csproj.basic.repository.SiteRepository;
import com.csproj.basic.service.dto.PDADTO;
import com.csproj.basic.service.dto.SiteDTO;
import com.csproj.basic.service.mapper.SiteMapper;
import com.csproj.siiat.base.common.dto.BaseDTO;
import com.csproj.siiat.base.common.exception.BaseAppException;
import com.csproj.siiat.base.common.logback.Logback;
import com.csproj.siiat.base.common.util.FileUtils;
import com.csproj.siiat.base.common.util.poi.POIUtil;
import com.csproj.siiat.security.SecurityUtils;
import com.csproj.system.domain.UserInfo;
import com.csproj.system.repository.UserInfoRepository;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * service样例
 * TODO save、saveAndGetDTO、update、updateAndGetDTO、delete、
 * TODO findAll、findAllAndGetDTO、findPageList、findPageListAndGetDTO、findOne、findOneAndGetDTO
 *
 * TODO @Transactional 事务注解
 * TODO @service 依赖注入
 */
@Service
@Transactional
public class SiteService extends BasicService<SiteDTO> {


    private final Logger log = LoggerFactory.getLogger(SiteService.class);

    @Resource(name = "siteRepository")
    private SiteRepository siteRepository;
    @Resource(name = "userInfoRepository")
    private UserInfoRepository userInfoRepository;

    private SiteMapper siteMapper;


    public SiteService(SiteRepository siteRepository,SiteMapper siteMapper,UserInfoRepository userInfoRepository) {
        this.siteMapper = siteMapper;
        this.siteRepository = siteRepository;
        this.userInfoRepository=userInfoRepository;
    }

    /**
     * 保存机构并且返回前端需要发的dto，包括扩展属性createName
     * @param siteDTO
     * @return siteDTO
     * TODO 主要负责从前端接收值
     * TODO 其他业务方法，比如保存试卷时同时保存章节
     * TODO DTO的扩展属性，在此方法复制
     */
    public SiteDTO saveAndGetDTO(SiteDTO siteDTO) {
        Site site = siteMapper.toEntity(siteDTO);
        site = save(site);
        siteDTO = siteMapper.toDto(site);

        extendSiteTypeName(siteDTO);
        return siteDTO;
    }

    /**
     * 保存机构
     * @param site
     * @return site
     * TODO 纯粹的保存方法，通用于所有保存业务调用
     * TODO 赋默认值，保存后，检查数据库，是否所有字段都有准确值
     */
    public Site save(Site site) {
        Site siteName = siteRepository.findFirstBySiteNameAndDeletedFlagIsFalse(site.getSiteName());

        if(StringUtils.isNotBlank(site.getId())){
            if(siteName!=null && !siteName.getId().equals(site.getId())) {
                throw new BaseAppException(false,"duplicate_name");
            }

        }else if(siteName!=null){
            throw  new BaseAppException(false,"duplicate_name");
        }

        //生成编号和code码
//        site.setManager(site.getManager()==null?"":site.getManager());
        site.setManagerId(site.getManagerId()==null?"":site.getManagerId());
        site.setManagerPhone(site.getManagerPhone()==null?"":site.getManagerPhone());
        site.setEnableFlag(true);
        site.setCreationTime(ZonedDateTime.now());
        site.setCreatorUserId(SecurityUtils.getCurrentUserId());
        site.setLastModificationTime(ZonedDateTime.now());
        site.setLastModifierUserId(SecurityUtils.getCurrentUserId());
        site.setDeletedFlag(false);
        return siteRepository.save(site);
    }

    /**
     * 保存机构
     * @param sites
     * @return site
     * TODO 纯粹的保存方法，通用于所有保存业务调用
     * TODO 赋默认值，保存后，检查数据库，是否所有字段都有准确值
     */
    public List<Site> batchSave(List<Site> sites) {
        for (int i = 0; i<sites.size(); i++){
            Site site = sites.get(i);
            //生成编号和code码
//            site.setManager(site.getManager()==null?"":site.getManager());
            site.setManagerId(site.getManagerId()==null?"":site.getManagerId());
            site.setManagerPhone(site.getManagerPhone()==null?"":site.getManagerPhone());
            site.setEnableFlag(true);
            site.setCreationTime(ZonedDateTime.now());
            site.setCreatorUserId(SecurityUtils.getCurrentUserId());
            site.setLastModificationTime(ZonedDateTime.now());
            site.setLastModifierUserId(SecurityUtils.getCurrentUserId());
            site.setDeletedFlag(false);
        }

        return siteRepository.save(sites);
    }

    /**
     * 修改机构并且返回前端需要发的dto，包括扩展属性
     * @param siteDTO
     * @return siteDTO
     * TODO 类似SAVE
     */
    public SiteDTO updateAndGetDTO(SiteDTO siteDTO) {
        Site site = update(siteMapper.toEntity(siteDTO));
        SiteDTO result = siteMapper.toDto(site);

        extendSiteTypeName(result);
        return siteDTO;
    }

    /**
     * 修改机构
     * @param site
     * @return site
     * TODO 类似SAVE
     */
    public Site update(Site site) {

        Site siteName = siteRepository.findFirstBySiteNameAndDeletedFlagIsFalse(site.getSiteName());

        if(StringUtils.isNotBlank(site.getId())){
            if(siteName!=null && !siteName.getId().equals(site.getId())) {
                throw new BaseAppException(false,"duplicate_name");
            }

        }else if(siteName!=null){
            throw  new BaseAppException(false,"duplicate_name");
        }

        Site siteDB = findOne(site.getId());
        siteDB.setSiteName(site.getSiteName());
        siteDB.setAddress(site.getAddress());
        siteDB.setRadius(site.getRadius());
        siteDB.setLng(site.getLng());
        siteDB.setLat(site.getLat());
//        siteDB.setManager(site.getManager()==null?"":site.getManager());
        siteDB.setManagerId(site.getManagerId()==null?"":site.getManagerId());
        siteDB.setManagerPhone(site.getManagerPhone()==null?"":site.getManagerPhone());
        siteDB.setSitePhone(site.getSitePhone());
        siteDB.setSiteType(site.getSiteType());
        siteDB.setLastModificationTime(ZonedDateTime.now());
        siteDB.setLastModifierUserId(SecurityUtils.getCurrentUserId());
        siteDB = siteRepository.save(siteDB);
        return siteDB;
    }
    /**
     *  获取所有站点信息
     *  @return the list of entities
     */
    @Transactional(readOnly = true)
    public List<SiteDTO> findAll() {
        List<SiteDTO> result = siteRepository.findAll().stream()
                .map(siteMapper::toDto)
                .collect(Collectors.toCollection(LinkedList::new));
        extendSiteTypeName(result);
        return result;
    }

    /**
     *  获取所有启用站点信息
     *  @return the list of entities
     */
    @Transactional(readOnly = true)
    public List<SiteDTO> findAllEnabled() {
        List<SiteDTO> result = siteRepository.findByEnabled().stream()
                .map(siteMapper::toDto)
                .collect(Collectors.toCollection(LinkedList::new));
        extendSiteTypeName(result);
        return result;
    }
    /**
     *  获取所有机构信息（分页）
     *  @return the list of entities
     *
     *  TODO 返回纯粹的数据库对象，不包含扩展属性，适用于所有调取业务方法
     */
    @Transactional(readOnly = true)
    public Page<Site> findPageList(Map<String, Object> map, Pageable pageable) {
        Page<Site> result = siteRepository.findPageList(map,pageable);
        return result;
    }

    /**
     *  获取所有机构信息（分页）
     *  @return the list of entities
     *
     *  TODO 返回DTO，包含扩展属性
     *  TODO 如果扩展属性不同，findPageListAndGetDTO1、findPageListAndGetDTO2，注明扩展的属性
     */
    @Transactional(readOnly = true)
    public BaseDTO findPageListAndGetDTO(Map<String,Object> map, Pageable pageable) {
        Page<Site> result = findPageList(map,pageable);
        List<Site> sites = result.getContent();
        List<SiteDTO> siteDTOs = siteMapper.toDto(sites);

        extendSiteTypeName(siteDTOs);
        extendManagerName(siteDTOs);
        return BaseDTO.createBaseDTO(result).setFieldList(siteDTOs);
    }


    /**
     * 根据id，获取机构信息
     *  @param id 主键id
     *  @return creator、questionTypeName
     *
     *  TODO 返回DTO，包含扩展属性
     *  TODO 如果扩展属性不同，findPageListAndGetDTO1、findPageListAndGetDTO2，注明扩展的属性
     */
    @Transactional(readOnly = true)
    public SiteDTO findOneAndGetDTO(String id) {
        Site site = findOne(id);
        SiteDTO siteDTO = siteMapper.toDto(site);
        siteDTO = siteMapper.toDto(site);
        extendSiteTypeName(siteDTO);
        return siteDTO;
    }

    /**
     * 根据id，获取机构信息
     *  @param id the id of the entity
     *  @return the entity
     *
     *  TODO 返回纯粹的数据库对象，不包含扩展属性，适用于所有调取业务方法
     */
    @Transactional(readOnly = true)
    public Site findOne(String id) {
        if(!StringUtils.isNotBlank(id)){
            return null;
        }
        Site site = siteRepository.findOne(id);
        if(site == null){
            throw new BaseAppException(BaseDTO.CODE_PARAM,"id_errors");
        }
        return site;
    }

    /**
     *  根据id，删除机构信息
     *  @param id the id of the entity
     */
    public void delete(String id) {
        Site siteDB = findOne(id);
        siteDB.setDeletedFlag(true);
        siteDB.setDeletionTime(ZonedDateTime.now());
        siteDB.setDeleterUserId(SecurityUtils.getCurrentUserId());
        siteDB = siteRepository.save(siteDB);
    }

    /**
     *  genju
     *  @param id the id of the entity
     */
    public SiteDTO enableFlag(String id, Boolean enableFlag) {
        Site siteDB = findOne(id);
        siteDB.setEnableFlag(enableFlag);
        siteDB.setLastModifierUserId(SecurityUtils.getCurrentUserId());
        siteDB.setLastModificationTime(ZonedDateTime.now());
        siteDB = siteRepository.save(siteDB);

        SiteDTO result = siteMapper.toDto(siteDB);
        extendSiteTypeName(result);
        return result;
    }
    /**
     * 设置站点的使用状态：禁用，启用，默认为启用
     * @param siteDTO
     * @return
     */
    public SiteDTO updateSiteStatus(SiteDTO siteDTO) {
        log.debug("Request to update UserInfo isUse : {}", siteDTO);
        Site site = siteRepository.findOne(siteDTO.getId());
        Boolean isUse = siteDTO.getEnableFlag();
        if (isUse != null && !"".equals(isUse)) {
            site.setEnableFlag(isUse);
        } else {
            site.setEnableFlag(true);
        }
        site.setReason(siteDTO.getReason());
        site = siteRepository.save(site);
        SiteDTO result = siteMapper.toDto(site);
        return result;
    }

    /**
     * 上传文件
     * @param file
     */
    public BaseDTO  batchImport(MultipartFile file){
        try {
            List<String[]> readResult = POIUtil.readExcel(file);

            if(readResult.size()==0)
            {
                return  BaseDTO.createBaseDTO().setSuccess(false).setMessage("upload_faild");
            }
            List<Site> sites = new ArrayList<>();
            StringBuilder errmsg = new StringBuilder();
            List<UserInfo> userInfos = userInfoRepository.findAll();
            int i = 2;
            for (String[] u : readResult) {
                try {
                    Site uname = siteRepository.findFirstBySiteNameAndDeletedFlagIsFalse(u[0]);
                    if(uname!=null){
                        errmsg.append(i-1).append(",");
                    }else{

                        Site site = new Site();
                        i++;
                        site.setDeletedFlag(false);
                        site.setEnableFlag(true);
                        site.setSiteName(u[0]);
                        site.setAddress(u[1]);

                        site.setLng(new BigDecimal(u[2]));
                        site.setLat(new BigDecimal(net.logstash.logback.encoder.org.apache.commons.lang.StringUtils.trim(u[3])));
                        site.setRadius(new BigDecimal(net.logstash.logback.encoder.org.apache.commons.lang.StringUtils.trim(u[4])));
                       if(StringUtils.isNotBlank(u[5]))
                       {
                           UserInfo userInfo = userInfos.stream().filter(s->s.getName().equals(StringUtils.trim(u[5]))).findFirst().orElse(new UserInfo());
                           site.setManagerId(userInfo.getId());
                       }

                        site.setManagerPhone(u[6]);
                        site.setSitePhone(u[7]);
                        sites.add(site);
                    }

                }catch (Exception e){
                    errmsg.append(i-1).append(",");
                }
            }

            if(sites.size()>0)
                siteRepository.save(sites);
            String msg = "";
            if(errmsg.length()>0)
            {
                return  BaseDTO.createBaseDTO().setSuccess(false).setMessage("partial_upload_faild");
            }
        } catch (IOException e) {
            throw new BaseAppException(false,"upload_error");
        }
        return BaseDTO.createBaseDTO().setSuccess(true);
    }
}
